N-queens¶
Time: O(N!); Space: O(N); hard
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space respectively.
Example 1:
Input: n = 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."
]
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."
]
]
Explanation:
There exist two distinct solutions to the 4-queens puzzle as shown above.
[1]:
class Solution1(object):
"""
Time: O(N!)
Space: O(N)
"""
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
def dfs(curr, cols, main_diag, anti_diag, result):
row, n = len(curr), len(cols)
if row == n:
result.append(map(lambda x: '.'*x + "Q" + '.'*(n-x-1), curr))
return
for i in range(n):
if cols[i] or main_diag[row+i] or anti_diag[row-i+n]:
continue
cols[i] = main_diag[row+i] = anti_diag[row-i+n] = True
curr.append(i)
dfs(curr, cols, main_diag, anti_diag, result)
curr.pop()
cols[i] = main_diag[row+i] = anti_diag[row-i+n] = False
result = []
cols, main_diag, anti_diag = [False]*n, [False]*(2*n), [False]*(2*n)
dfs([], cols, main_diag, anti_diag, result)
return result
[3]:
s = Solution1()
n = 4
assert s.solveNQueens(n) == [".Q..", "...Q", "Q...", "..Q."] or ["..Q.", "Q...", "...Q", ".Q.."]
[4]:
# For any point (x,y), if we want the new point (p,q) don't share the same row, column, or diagonal.
# then there must have ```p+q != x+y``` and ```p-q!= x-y```
# the former focus on eliminate 'left bottom right top' diagonal
# the latter focus on eliminate 'left top right bottom' diagonal
# - col_per_row: the list of column index per row
# - cur_row:current row we are seraching for valid column
# - xy_diff:the list of x-y
# - xy_sum:the list of x+y
class Solution2(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
def dfs(col_per_row, xy_diff, xy_sum):
cur_row = len(col_per_row)
if cur_row == n:
ress.append(col_per_row)
for col in range(n):
if col not in col_per_row and cur_row-col not in xy_diff and cur_row+col not in xy_sum:
dfs(col_per_row+[col], xy_diff+[cur_row-col], xy_sum+[cur_row+col])
ress = []
dfs([], [], [])
return [['.'*i + 'Q' + '.'*(n-i-1) for i in res] for res in ress]
[5]:
s = Solution2()
n = 4
assert s.solveNQueens(n) == [".Q..", "...Q", "Q...", "..Q."] or ["..Q.", "Q...", "...Q", ".Q.."]